package sourceapi.client.mainpage;

import java.util.ArrayList;
import java.util.Iterator;

import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Style;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.MouseDownEvent;
import com.google.gwt.event.dom.client.MouseDownHandler;
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.RequestException;
import com.google.gwt.http.client.Response;
import com.google.gwt.http.client.URL;
import com.google.gwt.json.client.*;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.*;

public class Native extends Base {
	
	private static  ArrayList<Native> SavedData = new ArrayList<Native>();
	
	public String Name;
	public String Fullname;
	public String Description;
	public String Extra;
	
	public String[] InputKeys;
	public String[] InputValues;
	
	public String ReturnDescription;
	public String OnError;
	public HorizontalPanel Owner;
	public int Line;
	
	private VerticalPanel  ContentCointeiner;
	
	public Native( JSONObject Values ){
		
		this.Name = Values.get("name").isString().stringValue();
		this.Fullname = Values.get("fullname").isString().stringValue();
		this.Description = Values.get("description").isString().stringValue();
		this.ReturnDescription = Values.get("return").isString().stringValue();
		this.OnError = Values.get("onerror").isString().stringValue();
		this.Owner = Base.GetHeader( Integer.parseInt( Values.get("owner").isString().stringValue() ) );
		this.Line = Integer.parseInt( Values.get("line").isString().stringValue() );
		this.Extra = Values.get("extra").isString().stringValue();
		
		JSONObject InputInformation = Values.get("input").isObject();
		
		if( InputInformation != null ){
			Iterator<String> InputNames = InputInformation.keySet().iterator();
			int Count = 0;
			
			InputKeys = new String[ InputInformation.size() ];
			InputValues = new String[ InputInformation.size() ];
			
			while( InputNames.hasNext() ){
				String key = InputNames.next(); //Get the key value
				
				InputKeys[ Count ] = key;	//First column is the input name
				InputValues[ Count ] = InputInformation.get(key).isString().stringValue();	//The description
				
				Count++;
			}
		}
		
		SavedData.add( this );
	}
	
	private void DisplayPage()
	{
		RootPanel Screen = RootPanel.get("MainBody");
		
		Screen.clear();
		
		ContentCointeiner = new VerticalPanel();
		ContentCointeiner.getElement().getStyle().setPadding(25.0, Unit.PX );
		ContentCointeiner.getElement().getStyle().setPaddingTop(0.0, Unit.PX );
		
		ContentCointeiner.add( this.Owner );
		
		
		ContentCointeiner.add( new HTML("<br><h2 style=\"padding-left: 10px;\">"+ this.Name +"</h2>") );
				
		
		//SYNTAX: A div with padding and changed font size
		ContentCointeiner.add( new HTML("<b>Syntax:</b>") );
		SimplePanel AllFunction = new SimplePanel();
		Style AllFunctionStyle = AllFunction.getElement().getStyle();
		AllFunctionStyle.setPaddingLeft(25.0, Unit.PX);
		AllFunctionStyle.setFontSize(9.0, Unit.PT);
		AllFunction.add( new HTML("<pre>" + this.Fullname + "</pre>") );
		ContentCointeiner.add( AllFunction );
		
		if( this.Extra.length() > 5 ){
			
			final HTML ExtraCode = new HTML( "<pre>"+this.Extra+"</pre>" ); 
			final Anchor OpenExtra = new Anchor("(more)");
			ExtraCode.getElement().getStyle().setPaddingLeft(25.0, Unit.PX);
			ExtraCode.getElement().getStyle().setFontSize(9.0, Unit.PT);
			OpenExtra.getElement().getStyle().setPaddingLeft(25.0, Unit.PX);
			
			ExtraCode.setVisible( false );
			
			OpenExtra.addMouseDownHandler( new MouseDownHandler(){
				public void onMouseDown(MouseDownEvent event) {
					ExtraCode.setVisible( true );
					OpenExtra.setVisible( false );
				}
			});
			
			ContentCointeiner.add( ExtraCode );
			ContentCointeiner.add( OpenExtra );
			
		}
		
		
		//USAGE
		if( this.InputKeys != null ){
			
			Grid UsageList = new Grid( this.InputKeys.length ,2 );		
			ContentCointeiner.add( new HTML("<br><b>Usage:</b>") );
			UsageList.getElement().getStyle().setPaddingLeft(25.0, Unit.PX);
			
			for( int i = 0; i < this.InputKeys.length; i++ ){
				UsageList.setHTML(i, 0, this.InputKeys[ i ] );	//First column is the input name
				UsageList.setHTML(i, 1, this.InputValues[ i ] );	//The description
			}
		
			ContentCointeiner.add( UsageList );
			
		}
			
		
		//NOTES
		ContentCointeiner.add( new HTML("<br><b>Notes:</b>") );
		SimplePanel Notes = new SimplePanel( );
		Notes.getElement().getStyle().setPaddingLeft(25.0, Unit.PX);
		Notes.add( new HTML( this.Description ) );
		
		ContentCointeiner.add( Notes );
		
		//RETURN
		ContentCointeiner.add( new HTML("<br><b>Return:</b>") );
		SimplePanel Return = new SimplePanel();
		Return.getElement().getStyle().setPaddingLeft(25.0, Unit.PX);
		Return.add( new HTML( this.ReturnDescription ) );
		
		ContentCointeiner.add( Return );
		
		//In case of Error
		if( this.OnError.length() > 5 ){
			ContentCointeiner.add( new HTML("<br><b>On Error:</b>") );
			SimplePanel OnErrorElem = new SimplePanel();
			OnErrorElem.getElement().getStyle().setPaddingLeft(25.0, Unit.PX);
			OnErrorElem.add( new HTML( this.OnError ) );
			
			ContentCointeiner.add( OnErrorElem );
		}
		
		Screen.add( ContentCointeiner );
	}
	
	public static void Display( final String Name ){
		
		//Do not let a request that is no longer needed keep going
		CancelRequest();
		
		if( DisplayByName( Name ) == true )
			return;
		
		//Page is not yet cached, we must go to the web and find it!
		String url = GWT.getHostPageBaseURL() + 
			"data/" + (GWT.isScript() == false ? "GetClientIP.txt" : "getnative.php") + "?id=" + Name;
		RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, URL.encode(url));
		
		try {		
			builder.setCallback( new RequestCallback(){

				public void onError(Request request, Throwable exception) {
					Window.alert( exception.getMessage() );
				}

				public void onResponseReceived(Request request, Response response) {
					if (200 == response.getStatusCode()) {
						LoadJson( JSONParser.parse( response.getText() ) );
						DisplayByName( Name );
					} else {
						//TODO: Show Error
					}
				}
				
			} );
			PageRequest = builder.send();
		} catch (RequestException e) {
		  // Couldn't connect to server        
		}	
		
	}
	
	public static boolean DisplayByName( String Name ){
		
		Iterator<Native> ListIter = SavedData.iterator();
		
		//Find if the page already is cached
		while( ListIter.hasNext() ){
			
			Native item = ListIter.next();
			
			if( Name.equalsIgnoreCase( item.Name ) ){
				item.DisplayPage();
				return true;
			}
			
		}
		
		return false;
		
	}
	
	public static void LoadJson( JSONValue data ){
		
		JSONArray ValueArray = data.isArray();
		
		if( ValueArray == null ){
			GWT.log("Failed to parse request: ", null );
			return;
		}
		
		for( int i = 0; i < ValueArray.size(); i++ ){
			
			JSONObject Item = ValueArray.get( i ).isObject();
			
			new Native( Item );
			
		}
		
	}
	
}
